#!/bin/bash

# 加载通用函数和Docker函数
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
source "$(dirname "${BASH_SOURCE[0]}")/docker.sh"

# 准备项目代码
prepare_project() {
    local project_name="$1"
    local projects_dir="$DEPLOY_SWARM_HOME/projects"
    local project_dir="$projects_dir/$project_name"
    
    debug "准备项目代码" >&2
    debug "项目目录: $project_dir" >&2
    
    # 确保项目目录存在
    mkdir -p "$projects_dir"
    
    # 检查项目是否已存在
    if [ ! -d "$project_dir" ]; then
        debug "项目不存在，开始克隆代码" >&2
        if ! git clone "$REPO_URL" "$project_dir" > /dev/null 2>&1; then
            debug "代码克隆失败" >&2
            handle_error "代码克隆失败"
        fi
        debug "代码克隆完成" >&2
    fi
    
    # 切换到项目目录
    cd "$project_dir" || handle_error "无法切换到项目目录"
    
    # 切换到指定分支并更新代码
    debug "切换到分支: $BRANCH" >&2
    if ! git checkout "$BRANCH" > /dev/null 2>&1; then
        debug "切换分支失败" >&2
        handle_error "切换分支失败"
    fi
    
    debug "拉取最新代码" >&2
    if ! git pull > /dev/null 2>&1; then
        debug "拉取代码失败" >&2
        handle_error "拉取代码失败"
    fi
    debug "代码更新完成" >&2
    
    # 获取最新的commit hash
    local commit_hash
    commit_hash=$(git rev-parse --short HEAD)
    debug "获取最新提交hash: $commit_hash" >&2
    
    # 切回工作目录
    cd - > /dev/null || handle_error "无法切回工作目录"
    
    echo "$project_dir:$commit_hash"
}

# 构建编译环境镜像并执行构建
build_builder_image() {
    local image_name="$1"
    local project_dir="$2"
    local target_path="$3"
    local env_suffix="${DEPLOY_ENV:-local}"
    local builder_image="${image_name}-${env_suffix}-builder"
    
    start_spinner "构建编译环境镜像..." >&2
    debug "开始构建编译环境镜像: $builder_image" >&2
    
    # 检查并初始化环境
    if [ -z "$DEPLOY_SWARM_HOME" ]; then
        debug "DEPLOY_SWARM_HOME 环境变量未设置" >&2
        stop_spinner "error" "DEPLOY_SWARM_HOME 环境变量未设置" >&2
        handle_error "DEPLOY_SWARM_HOME 环境变量未设置"
    fi
    
    # 确保临时目录存在
    init_temp_dir
    debug "临时目录初始化完成: $TEMP_DIR" >&2
    
    # 根据构建工具选择Dockerfile
    local dockerfile="Dockerfile.${BUILDER}"
    debug "使用构建工具: $BUILDER, Dockerfile: $dockerfile" >&2
    
    # 复制Dockerfile和SSH密钥到临时目录
    mkdir -p "$TEMP_DIR/ssh"
    cp "$DEPLOY_SWARM_HOME/lib/dockerfiles/$dockerfile" "$TEMP_DIR/Dockerfile"
    cp "$HOME/.ssh/id_rsa" "$TEMP_DIR/ssh/"
    debug "已复制Dockerfile和SSH密钥到临时目录: $TEMP_DIR" >&2
    debug "构建参数: DOCKER_MIRROR=$DOCKER_MIRROR, JDK_VERSION=$JDK_VERSION" >&2
    
    # 构建编译环境镜像
    local build_cmd="docker build"
    if ! $DEBUG_MODE; then
        build_cmd="$build_cmd --quiet"
    fi
    
    build_cmd="$build_cmd \
        --build-arg DOCKER_MIRROR=\"$DOCKER_MIRROR\" \
        --build-arg JDK_VERSION=\"$JDK_VERSION\" \
        -f \"$TEMP_DIR/Dockerfile\" \
        --no-cache \
        -t \"$builder_image\" \
        \"$TEMP_DIR\""
    
    local build_output
    debug "执行构建命令: $build_cmd" >&2
    
    if $DEBUG_MODE; then
        if ! build_output=$(eval "$build_cmd" 2>&1); then
            debug "编译环境镜像构建失败" >&2
            stop_spinner "error" "编译环境镜像构建失败" >&2
            handle_error "编译环境镜像构建失败"
        fi
        echo "$build_output" >&2
    else
        if ! build_output=$(eval "$build_cmd" 2>&1); then
            debug "编译环境镜像构建失败，查看日志: $BUILD_LOG" >&2
            stop_spinner "error" "编译环境镜像构建失败" >&2
            handle_error "编译环境镜像构建失败，详细信息请查看build.log"
        fi
        echo "$build_output" > "$BUILD_LOG"
    fi
    
    debug "编译环境镜像构建成功: $builder_image" >&2
    stop_spinner "success" "编译环境镜像构建成功" >&2

    # 执行构建并输出产物到本地目录
    start_spinner "执行构建..." >&2
    debug "开始在构建容器中执行构建" >&2

    # 创建依赖缓存目录
    local cache_dir="$DEPLOY_SWARM_HOME/cache/${BUILDER}"
    mkdir -p "$cache_dir"
    debug "创建依赖缓存目录: $cache_dir" >&2

    # 根据构建工具选择不同的构建命令和缓存目录
    local build_command="mvn clean package -DskipTests"
    local cache_mount="-v $cache_dir:/root/.m2/repository"
    local env_vars=""
    if [ "$BUILDER" = "gradle" ]; then
        build_command="gradle clean build --console plain --no-daemon -x test --info"
        cache_mount="-v $cache_dir:/home/gradle/.gradle/.tmp"
        env_vars="-e GRADLE_OPTS=-Dorg.gradle.daemon=false"
    fi
    debug "构建命令: $build_command" >&2
    debug "依赖缓存目录: $cache_dir" >&2
    debug "执行构建命令: $build_command" >&2

    # 运行构建容器
    local maven_output
    if ! maven_output=$(docker run --rm \
        -v "$(readlink -f "$project_dir"):/build" \
        $cache_mount \
        $env_vars \
        "$builder_image" \
        /bin/bash -c "cd /build && $build_command" 2>&1); then
        debug "构建失败" >&2
        stop_spinner "error" "构建失败" >&2
        handle_error "$maven_output"  # 在错误信息中包含Maven的输出
    fi

    debug "构建完成，产物已输出到项目目录" >&2
    if $DEBUG_MODE; then
        debug "构建产物列表:" >&2
        if [ "$BUILDER" = "gradle" ]; then
            ls -lh "$project_dir/build/libs" >&2
        else
            ls -lh "$project_dir$target_path" >&2
        fi
    fi
    stop_spinner "success" "构建完成" >&2

    # 清理构建镜像
    if ! docker rmi "$builder_image" &>/dev/null; then
        debug "清理构建镜像失败" >&2
        stop_spinner "error" "清理构建镜像失败" >&2
        handle_error "清理构建镜像失败"
    fi
}

# 构建运行镜像
build_runtime_image() {
    local image_name="$1"
    local project_dir="$2"
    local target_path="$3"

    start_spinner "构建运行镜像..." >&2
    debug "开始构建运行镜像: $image_name:$IMAGE_TAG" >&2
    
    # 创建运行时构建目录
    local runtime_dir="$TEMP_DIR/runtime"
    mkdir -p "$runtime_dir/target"
    debug "创建运行时构建目录: $runtime_dir" >&2
    
    # 复制Dockerfile和构建产物到运行时目录
    cp "$DEPLOY_SWARM_HOME/lib/dockerfiles/Dockerfile" "$runtime_dir/"

    # 复制Dockerfile
    debug "复制Dockerfile: $DEPLOY_SWARM_HOME/lib/dockerfiles/Dockerfile ===> $runtime_dir/Dockerfile" >&2
    
    # 复制构建产物
    debug "复制构建产物: $project_dir$target_path/*.jar ===> $runtime_dir/target/" >&2
    if [ "$BUILDER" = "gradle" ]; then
        cp -r "$project_dir/build/libs"/*.jar "$runtime_dir/target/"
    else
        cp -r "$project_dir$target_path"/*.jar "$runtime_dir/target/"
    fi
    debug "已复制Dockerfile和构建产物到运行时目录" >&2
    if $DEBUG_MODE; then
        debug "运行时目录构建产物列表:" >&2
        ls -lh "$runtime_dir/target" >&2
    fi
    debug "构建参数: DOCKER_MIRROR=$DOCKER_MIRROR, JDK_VERSION=$JDK_VERSION" >&2
    
    # 构建运行镜像
    local build_cmd="docker build"
    if ! $DEBUG_MODE; then
        build_cmd="$build_cmd --quiet"
    fi
    
    build_cmd="$build_cmd \
        --build-arg DOCKER_MIRROR=\"$DOCKER_MIRROR\" \
        --build-arg JDK_VERSION=\"$JDK_VERSION\" \
        -f \"$runtime_dir/Dockerfile\" \
        -t \"$image_name:$IMAGE_TAG\" \
        \"$runtime_dir\""
    
    local build_output
    debug "执行构建命令: $build_cmd" >&2
    
    if $DEBUG_MODE; then
        if ! build_output=$(eval "$build_cmd" 2>&1); then
            debug "运行镜像构建失败" >&2
            stop_spinner "error" "运行镜像构建失败" >&2
            handle_error "运行镜像构建失败"
        fi
        echo "$build_output" >&2
    else
        if ! build_output=$(eval "$build_cmd" 2>&1); then
            debug "运行镜像构建失败，查看日志: $BUILD_LOG" >&2
            stop_spinner "error" "运行镜像构建失败" >&2
            handle_error "运行镜像构建失败，详细信息请查看build.log"
        fi
        echo "$build_output" >> "$BUILD_LOG"
    fi
    
    debug "运行镜像构建成功: $image_name:$IMAGE_TAG" >&2
    stop_spinner "success" "运行镜像构建成功" >&2
}

# 清理无效镜像
cleanup_images() {
    local image_name="$1"
    
    start_spinner "清理无效镜像..." >&2
    debug "开始清理无效镜像" >&2
    
    # 清理悬空镜像、未使用的容器
    local prune_output
    if ! prune_output=$(docker system prune -f 2>&1); then
        debug "清理无效资源失败: $prune_output" >&2
        stop_spinner "error" "清理无效资源失败" >&2
        return 1
    fi
    debug "清理无效资源成功: $prune_output" >&2
    
    debug "镜像清理完成" >&2
    stop_spinner "success" "镜像清理完成" >&2
}

# 执行完整的构建流程
do_build() {
    local image_name="$1"
    local target_path="$2"
    debug "开始执行构建流程: $image_name" >&2
    
    # 检查Docker环境
    check_docker
    
    # 准备项目代码并获取commit hash
    local project_info
    project_info=$(prepare_project "$image_name")
    local project_dir
    local commit_hash
    project_dir=$(echo "$project_info" | cut -d':' -f1)
    commit_hash=$(echo "$project_info" | cut -d':' -f2)
    
    # 设置镜像标签
    set_image_tag "$image_name" "$commit_hash"
    
    # 执行构建步骤
    build_builder_image "$image_name" "$project_dir" "$target_path"
    build_runtime_image "$image_name" "$project_dir" "$target_path"
    
    # 所有任务完成后再执行清理
    cleanup "true"
    
    # 返回镜像标签
    get_image_tag
}
